<?php
/**
 * panx后台物资的管理
 *
 * Author: lyun
 * Date: 2018/7/10
 * Created by Panxsoft.
 */


namespace App\Http\Controllers\Admin\Panx;

use App\Http\Controllers\ApiController;
use App\Http\Requests\Admin\Panx\Material\MaterialStoreRequest;
use App\Http\Requests\Admin\Panx\Material\MaterialUpdateRequest;
use App\Http\Requests\Admin\Panx\Material\StoreMaterialPurchaseRequest;
use App\Models\Customer\Customer;
use App\Models\Panx\Material;
use App\Models\Panx\MaterialPurchase;
use App\Models\Panx\MaterialSale;
use App\Services\Utils\TimeHelper;
use App\Services\Utils\Transaction;
use Illuminate\Http\Request;

class MaterialController extends ApiController
{
    const DEFAULT_ORDER_BYS_INDEX = [
        ['order_by' => 'purchase_at', 'sort' => 'DESC'],
    ];

    const DEFAULT_ORDER_BYS_SELL_LIST = [
        ['order_by' => 'sold_at', 'sort' => 'DESC'],
    ];

    const ROUTE_NAMES = [
        'index'                 => 'admin.panx.material.index',
        'sellList'              => 'admin.panx.material.sellList',
        'store'                 => 'admin.panx.material.store',
        'storeMaterialPurchase' => 'admin.panx.material.storeMaterialPurchase',
        'update'                => 'admin.panx.material.update',
    ];


    /**
     * 采购物资记录表
     * @test
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $material_purchases = MaterialPurchase::filterName($request->name)
            ->filterManufacturer($request->manufacturer)
            ->filterBuyer($request->buyer)
            ->filterTimeRange($request->time_range, 'purchase_at')
            ->orderBys($request->order_by, self::DEFAULT_ORDER_BYS_INDEX)
            ->with('material')
            ->paginate($request->per_page?:15);

        return $this->response(compact('material_purchases'));
    }

    /**
     * 出售物资记录表
     * @test
     *
     * @param Request $request
     * @return array|\Illuminate\Http\Response
     */
    public function sellList(Request $request)
    {
        $material_sales = MaterialSale::filterCustomerId($request->customer_id)
            ->filterOperator($request->operator)
            ->filterName($request->name)
            ->filterTimeRange($request->time_range, 'sold_at')
            ->orderBys($request->order_by, self::DEFAULT_ORDER_BYS_SELL_LIST)
            ->with('customer', 'materialPurchase.material')
            ->paginate($request->per_page?:15);

        return $this->response(compact('material_sales'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $customers = Customer::where('is_deleted', Customer::IS_NOT_DELETED)
            ->latest()
            ->get(['id', 'name']);

        $materials = Material::latest()
            ->get(['id', 'name']);

        return $this->response(compact('customers', 'materials'));
    }

    /**
     * 保存 采购物资信息 和 采购记录
     * @test
     *
     * @param  MaterialStoreRequest  $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(MaterialStoreRequest $request)
    {
        $material_data = $this->assembleMaterial($request);
        $material_purchase_data = $this->assembleMaterialPurchase($request);

        $stored = Transaction::handle(function() use($material_data, $material_purchase_data){

            $material = Material::create($material_data);

            $material_purchase_data += ['material_id'=>$material->id];
            $material_purchase = MaterialPurchase::create($material_purchase_data);

            $material_purchase->material = $material;

            return $material_purchase;
        });

        return $this->response(compact('stored'));
    }

    /**
     * 从已有采购物资信息,保存采购记录
     * @test
     *
     * @param  StoreMaterialPurchaseRequest  $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function storeMaterialPurchase(StoreMaterialPurchaseRequest $request)
    {
        $material = Material::find($request->material_id);
            $this->checkItemExist($material, '物资');

        $material_purchase_data = $this->assembleMaterialPurchase($request);

        $stored = Transaction::handle(function() use($material, $material_purchase_data){

            $material_purchase_data += ['material_id'=>$material->id];
            $material_purchase = MaterialPurchase::create($material_purchase_data);

            $material_purchase->material = $material;

            return $material_purchase;
        });

        return $this->response(compact('stored'));
    }

    /**
     * 保存售卖物资信息
     * @test
     *
     * @param  MaterialUpdateRequest  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function update(MaterialUpdateRequest $request, $id)
    {
        /** @var MaterialPurchase $material_purchase */
        $material_purchase = MaterialPurchase::find($id);
            $this->checkItemExist($material_purchase, '采购物资记录');

        $stock = $material_purchase->stock - $request->num;
            $this->checkIsTrue($stock >= 0, '出售数量错误！');

        $material_sale_data = $this->assembleMaterialSale($request, $id);

        $updated = Transaction::handle(function() use ($stock, $material_sale_data, $material_purchase){

            $material_purchase->update(['stock'=>$stock]);
            $updated = MaterialSale::create($material_sale_data);

            return $updated;
        });

        return $this->response(compact('updated'));
    }

    /**
     * @param MaterialStoreRequest $request
     * @return array
     */
    private function assembleMaterial(MaterialStoreRequest $request)
    {
        return [
            'name'           => $request->name,
            'code'           => $request->code,
            'specifications' => $request->specifications,
            'manufacturer'   => $request->manufacturer,
        ];
    }

    /**
     * @param MaterialStoreRequest|Request|StoreMaterialPurchaseRequest $request
     * @return array
     */
    private function assembleMaterialPurchase(Request $request)
    {
        return [
            'sku'            => $request->sku,
            'stock'          => $request->sku,
            'buyer'          => $request->buyer,
            'purchase_at'    => TimeHelper::toNowIfToday(TimeHelper::tryToCarbonOrNow($request->purchase_at)),
            'remark'         => $request->remark,
        ];
    }

    /**
     * @param MaterialUpdateRequest $request
     * @param $id
     * @return array
     */
    private function assembleMaterialSale(MaterialUpdateRequest $request, $id)
    {
        return [
            'material_purchase_id' => $id,
            'customer_id'          => $request->customer_id,
            'num'                  => $request->num,
            'sold_at'              => TimeHelper::toNowIfToday(TimeHelper::tryToCarbonOrNow($request->sold_at)),
            'operator'             => $request->operator,
            'remark'               => $request->remark
        ];
    }
}
